`include "./module_SHL2.v"
`include "./module_Mux2.v"
`include "./module_Mux4.v"
`include "./module_ALU.v"
`include "./module_ALUOut.v"
`include "./module_ALUCU.v"
`include "./module_Areg.v"
`include "./module_Breg.v"
`include "./module_CU.v"
`include "./module_IR.v"
`include "./module_MDR.v"
`include "./module_Mem.v"
`include "./module_PC.v"
`include "./module_RF.v"
`include "./module_SigExt.v"
`include "./module_SR.v"

module CPU(
        input CLK,
        input RST
    );
    //控制信号
    wire PCWr;
    wire PCWrCond;
    wire IorD;
    wire MemRd;
    wire MemWr;
    wire IRWr;
    wire MemtoReg;
    wire ALUSrcA;
    wire RegWr;
    wire RegDst;

    wire [1:0] PCSrc;
    wire [1:0] ALUOp;
    wire [1:0] ALUSrcB;

    //IR输出线
    wire [5:0] opcode; //31-26
    wire [4:0] rs; //25-21
    wire [4:0] rt; //20-16
    wire [4:0] rd; //15-11
    wire [4:0] shamt;  //10-6
    wire [5:0] func;   //5-0
    wire [15:0] immediate_16; //15-0
    wire [25:0] immediate_26; //25-0

    //PC输入输出线
    wire [31:0] PC_in, PC_out;
    // 存储器线
    wire [31:0] Addr, R_data, W_data;
    // RF线
    wire [31:0] RFR_data1, RFR_data2, RFW_data;
    wire [4:0] RFW_Reg;
    // 符号扩展线
    wire [31:0] SigExt_out;
    // MDR线
    wire [31:0] MDR_out;
    // Areg与Breg线
    wire [31:0] A_out;
    wire [31:0] B_out;
    // 分支左移线
    wire [31:0] branchAddr;
    // 未拼接PC+4的跳转地址
    wire [27:0] tempjumpAddr;
    // LW/SW偏移量线
    wire [31:0] LSOffset;
    // ALUCU输出线
    wire [3:0] ALUCtrl;

    // ALU线和ALUOut线
    wire [31:0] ALU_a, ALU_b, ALU_result;
    wire isZero;
    wire [31:0] ALUOut_out;
    // CU状态控制
    wire [5:0] State;
    wire [5:0] Nextstate;

    assign W_data = B_out;
    assign LSOffset = SigExt_out;

    SR sr(
           .CLK(CLK),
           .S(State),
           .NS(Nextstate),
           .Rst(RST)
       );



    PC pc(
           .CLK(CLK),//1
           .RST(RST),//1
           .PCWr((isZero & PCWrCond) | PCWr),//1
           .D(PC_in),//32
           .Q(PC_out)//32
       );

    Mux2 IorD_mux(
             .MUXin0(PC_out),//32
             .MUXin1(ALUOut_out),   //32
             .MUXctrl0to1(IorD),    //1
             .MUXout(Addr)//32
         );

    Mem mem(
            .Addr(Addr),//32
            .R_data(R_data),//32
            .W_data(W_data),    //32
            .MemRd(MemRd),//1
            .MemWr(MemWr)//1
        );

    IR ir(
           .CLK(CLK),//
           .IRWr(IRWr),
           .D(R_data),
           .opcode(opcode),
           .rs(rs),
           .rt(rt),
           .rd(rd),
           .shamt(shamt),
           .func(func),
           .immediate_16(immediate_16),
           .immediate_26(immediate_26)
       );

    MDR mdr(
            .clk(CLK),
            .D(R_data),
            .Q(MDR_out)
        );

    Mux2 #(32) MemtoReg_mux(
             .MUXin0(ALUOut_out),
             .MUXin1(MDR_out),
             .MUXctrl0to1(MemtoReg),
             .MUXout(RFW_data)
         );

    Mux2 #(5) RegDst_mux(
             .MUXin0(rt),
             .MUXin1(rd), //BUG
             .MUXctrl0to1(RegDst),
             .MUXout(RFW_Reg)
         );

    RF rf(
           .R_Reg1(rs),
           .R_Reg2(rt),
           .W_Reg(RFW_Reg),
           .W_data(RFW_data),
           .clk(CLK),
           .rst(RST),
           .RegWr(RegWr),
           .R_data1(RFR_data1),
           .R_data2(RFR_data2)
       );

    Areg areg(
             .D(RFR_data1),
             .clk(CLK),
             .Q(A_out)
         );

    Breg breg(
             .D(RFR_data2),
             .clk(CLK),
             .Q(B_out)
         );

    Mux2 #(32) ALUSrcA_mux(
             .MUXin0(PC_out),
             .MUXin1(A_out),
             .MUXctrl0to1(ALUSrcA),
             .MUXout(ALU_a)
         );

    SigExt sigext(
               .in(immediate_16),
               .out(SigExt_out)
           );

    SHL2 #(32) branchshl2(
             .SHL2input(SigExt_out),
             .SHL2output(branchAddr)//debug
         );

    Mux4 ALUSrcB_mux(
             .MUXin0(B_out),
             .MUXin1(32'd4),
             .MUXin2(LSOffset),
             .MUXin3(branchAddr),
             .MUXctrl0to3(ALUSrcB),
             .MUXout(ALU_b)
         );

    ALUCU alucu(
              .ALUOp(ALUOp),
              .funct(func),
              .ALUCtrl(ALUCtrl)
          );

    ALU alu(
            .A(ALU_a),
            .B(ALU_b),
            .M(ALUCtrl),
            .C(ALU_result),
            .Z(isZero)
        );

    ALUOut aluout(
               .ALU_result(ALU_result),
               .clk(CLK),
               .ALU_result_out(ALUOut_out)
           );

    SHL2 #(26) jumpshl2(
             .SHL2input(immediate_26),
             .SHL2output(tempjumpAddr)
         );


    Mux4 PCSrc_mux(
             .MUXin0(ALU_result),
             .MUXin1(ALUOut_out),
             .MUXin2({PC_out[31:28],tempjumpAddr}),
             .MUXin3(32'd0),
             .MUXctrl0to3(PCSrc),
             .MUXout(PC_in)
         );

    CU cu(
           .Op(opcode),
           .S(State),
           .PCWr(PCWr),
           .PCWrCond(PCWrCond),
           .IorD(IorD),
           .MemRd(MemRd),
           .MemWr(MemWr),
           .IRWr(IRWr),
           .MemtoReg(MemtoReg),
           .ALUSrcA(ALUSrcA),
           .RegWr(RegWr),
           .RegDst(RegDst),
           .PCSrc(PCSrc),
           .ALUOp(ALUOp),
           .ALUSrcB(ALUSrcB),
           .NS(Nextstate)
       );



endmodule
